package com.example.performance.r2dbc;

import com.example.performance.r2dbc.compare.JdbcService;
import com.example.performance.r2dbc.compare.JdbcStreamingService;
import com.example.performance.r2dbc.entity.JDBCRowMapper;
import com.example.performance.r2dbc.entity.RecordDb;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


/**
 * @author zpMeng
 * @since 6/19/2025
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("jdbc")
public class JDBCController {

    private final JdbcTemplate jdbcTemplate;
    private final JdbcService jdbcService;
    private final JdbcStreamingService jdbcStreamingService;

    @GetMapping("prepare")
    public void prepareData() {
        for (int i = 0; i <= 19; i++) {
            String tableName = "ds_agg_427_%d".formatted(i);
            Long count = jdbcTemplate.queryForObject("select count(1) from %s".formatted(tableName), Long.class);
            System.out.printf("%s: %d%n", tableName, count);
            System.out.println();
        }
    }

    @GetMapping
    public void jdbcPerformance(Long nodeId) {
        String sql = "select * from DS_AGG_427_0 where node_Id <= %d".formatted(nodeId);

        for (int i = 0; i < 5; i++) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();

            List<RecordDb> query = jdbcTemplate.query(sql, new JDBCRowMapper());
            System.out.println(query.size());

            stopWatch.stop();
            System.out.println("JDBC 耗时: " + stopWatch.prettyPrint());
        }
    }

    @GetMapping("serial")
    public void serial() {
        jdbcWarmUp();

        jdbcService.testSerialPerformance();
    }

    @GetMapping("parallel")
    public void parallel(int start, int end, int nodeSize) throws InterruptedException {
        System.out.println("warm up started");
        jdbcService.testOneConcurrencyPerformance(5, 3, 100);
        System.out.println("warm up finished");

        jdbcService.testParallelPerformance(start, end, nodeSize);

        System.out.println("jdbc parallel finished");
    }

    @GetMapping("serial/flux")
    public void serialWithFlux() {
        System.out.println("jdbc flux serial started");

        fluxWarmUp();

        jdbcStreamingService.testStreamQuerySerial();

        System.out.println("jdbc flux serial ended");
    }

    @GetMapping("parallel/flux")
    public void cursorParallel(int start, int end, int nodeSize) throws Exception {
        System.out.println("jdbc flux parallel started");

        fluxWarmUp();

        jdbcStreamingService.testStreamQueryParallel(start, end, nodeSize);

        System.out.println("jdbc flux parallel ended");
    }

    private void jdbcWarmUp() {
        System.out.println("warm up started");
        for (int i = 0; i < 10; i++) {
            jdbcService.executeOneJdbcQuery(0, 1000L);
        }
        System.out.println("warm up finished");
    }

    private void fluxWarmUp() {
        System.out.println("warm up started");
        for (int i = 0; i < 10; i++) {
            jdbcStreamingService.executeOneFluxQueryByStream(0, 1000L);
        }
        System.out.println("warm up finished");
    }

}